From bf753c8c6b7a8d171365c8eaa23826dc057dd3c5 Mon Sep 17 00:00:00 2001 From: "iap10@firebug.cl.cam.ac.uk" Date: Wed, 7 Sep 2005 02:31:24 +0000 Subject: [PATCH] Extend save/restore interface to cope with domains >4GB by adding a level of indirection. Signed-off-by: ian@xensource.com --- .../arch/xen/i386/kernel/setup.c | 36 +++++++++++++----- linux-2.6-xen-sparse/arch/xen/kernel/reboot.c | 26 +++++++++---- .../arch/xen/x86_64/kernel/setup.c | 37 ++++++++++++++++--- tools/libxc/xc_linux_save.c | 18 +++++++-- xen/include/public/arch-x86_32.h | 7 +++- xen/include/public/arch-x86_64.h | 7 +++- 6 files changed, 100 insertions(+), 31 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c index 2479d87972..1855042fa0 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c @@ -359,7 +359,8 @@ static void __init probe_roms(void) shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; EXPORT_SYMBOL(HYPERVISOR_shared_info); -unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list; +unsigned long *phys_to_machine_mapping; +unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[16]; EXPORT_SYMBOL(phys_to_machine_mapping); /* Raw start-of-day parameters from the hypervisor. */ @@ -1519,7 +1520,7 @@ static void set_mca_bus(int x) { } */ void __init setup_arch(char **cmdline_p) { - int i, j; + int i, j, k, fpp; physdev_op_t op; unsigned long max_low_pfn; @@ -1669,14 +1670,31 @@ void __init setup_arch(char **cmdline_p) sizeof(unsigned long)))); } - pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE); - for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) - { - pfn_to_mfn_frame_list[j] = - virt_to_mfn(&phys_to_machine_mapping[i]); + + /* + * Initialise the list of the frames that specify the list of + * frames that make up the p2m table. Used by save/restore + */ + pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE); + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(pfn_to_mfn_frame_list_list); + + fpp = PAGE_SIZE/sizeof(unsigned long); + for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ ) + { + if ( (j % fpp) == 0 ) + { + k++; + BUG_ON(k>=16); + pfn_to_mfn_frame_list[k] = alloc_bootmem_low_pages(PAGE_SIZE); + pfn_to_mfn_frame_list_list[k] = + virt_to_mfn(pfn_to_mfn_frame_list[k]); + j=0; + } + pfn_to_mfn_frame_list[k][j] = + virt_to_mfn(&phys_to_machine_mapping[i]); } - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list = - virt_to_mfn(pfn_to_mfn_frame_list); + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; /* * NOTE: at this point the bootmem allocator is fully available. diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index 50e645a69f..87eb53bebb 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -67,7 +67,7 @@ static int shutting_down = SHUTDOWN_INVALID; static int __do_suspend(void *ignore) { - int i, j; + int i, j, k, fpp; #ifdef CONFIG_XEN_USB_FRONTEND extern void usbif_resume(); @@ -81,7 +81,7 @@ static int __do_suspend(void *ignore) extern void time_suspend(void); extern void time_resume(void); extern unsigned long max_pfn; - extern unsigned long *pfn_to_mfn_frame_list; + extern unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[]; #ifdef CONFIG_SMP extern void smp_suspend(void); @@ -191,14 +191,24 @@ static int __do_suspend(void *ignore) HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); memset(empty_zero_page, 0, PAGE_SIZE); - - for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) + + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(pfn_to_mfn_frame_list_list); + + fpp = PAGE_SIZE/sizeof(unsigned long); + for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ ) { - pfn_to_mfn_frame_list[j] = - virt_to_mfn(&phys_to_machine_mapping[i]); + if ( (j % fpp) == 0 ) + { + k++; + pfn_to_mfn_frame_list_list[k] = + virt_to_mfn(pfn_to_mfn_frame_list[k]); + j=0; + } + pfn_to_mfn_frame_list[k][j] = + virt_to_mfn(&phys_to_machine_mapping[i]); } - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list = - virt_to_mfn(pfn_to_mfn_frame_list); + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; gnttab_resume(); diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c index 05dab06d4a..9b3d47b29c 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c @@ -76,7 +76,8 @@ EXPORT_SYMBOL(HYPERVISOR_shared_info); /* Allows setting of maximum possible memory size */ unsigned long xen_override_max_pfn; -unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list; +unsigned long *phys_to_machine_mapping; +unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[512]; EXPORT_SYMBOL(phys_to_machine_mapping); @@ -730,7 +731,7 @@ void __init setup_arch(char **cmdline_p) #endif #ifdef CONFIG_XEN { - int i, j; + int i, j, k, fpp; /* Make sure we have a large enough P->M table. */ if (end_pfn > xen_start_info->nr_pages) { phys_to_machine_mapping = alloc_bootmem( @@ -746,11 +747,35 @@ void __init setup_arch(char **cmdline_p) sizeof(unsigned long)))); } - pfn_to_mfn_frame_list = alloc_bootmem(PAGE_SIZE); - - for ( i=0, j=0; i < end_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) - pfn_to_mfn_frame_list[j] = + /* + * Initialise the list of the frames that specify the list of + * frames that make up the p2m table. Used by save/restore + */ + pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE); + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(pfn_to_mfn_frame_list_list); + + fpp = PAGE_SIZE/sizeof(unsigned long); + for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ ) + { + if ( (j % fpp) == 0 ) + { + k++; + BUG_ON(k>=fpp); + pfn_to_mfn_frame_list[k] = alloc_bootmem(PAGE_SIZE); + pfn_to_mfn_frame_list_list[k] = + virt_to_mfn(pfn_to_mfn_frame_list[k]); + j=0; + } + pfn_to_mfn_frame_list[k][j] = virt_to_mfn(&phys_to_machine_mapping[i]); + } + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; + + + + + } #endif diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index c9af7b0d3b..af32db7791 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -419,6 +419,7 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters, unsigned long page[1024]; /* A copy of the pfn-to-mfn table frame list. */ + unsigned long *live_pfn_to_mfn_frame_list_list = NULL; unsigned long *live_pfn_to_mfn_frame_list = NULL; unsigned long pfn_to_mfn_frame_list[1024]; @@ -506,11 +507,20 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters, goto out; } - /* the pfn_to_mfn_frame_list fits in a single page */ + live_pfn_to_mfn_frame_list_list = xc_map_foreign_range(xc_handle, dom, + PAGE_SIZE, PROT_READ, + live_shinfo->arch.pfn_to_mfn_frame_list_list); + + if (!live_pfn_to_mfn_frame_list_list){ + ERR("Couldn't map pfn_to_mfn_frame_list_list"); + goto out; + } + live_pfn_to_mfn_frame_list = - xc_map_foreign_range(xc_handle, dom, - PAGE_SIZE, PROT_READ, - live_shinfo->arch.pfn_to_mfn_frame_list ); + xc_map_foreign_batch(xc_handle, dom, + PROT_READ, + live_pfn_to_mfn_frame_list_list, + (nr_pfns+(1024*1024)-1)/(1024*1024) ); if (!live_pfn_to_mfn_frame_list){ ERR("Couldn't map pfn_to_mfn_frame_list"); diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index cf0a43c50c..f6c3ea9246 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -128,8 +128,11 @@ typedef struct vcpu_guest_context { } vcpu_guest_context_t; typedef struct arch_shared_info { - /* MFN of a table of MFNs that make up p2m table */ - u64 pfn_to_mfn_frame_list; + unsigned long max_pfn; /* max pfn that appears in table */ + unsigned long pfn_to_mfn_frame_list_list; + /* frame containing list of mfns + containing list of mfns + containing the p2m table. */ } arch_shared_info_t; #endif diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 81b1ecd6fd..3cb8a2a785 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -186,8 +186,11 @@ typedef struct vcpu_guest_context { } vcpu_guest_context_t; typedef struct arch_shared_info { - /* MFN of a table of MFNs that make up p2m table */ - u64 pfn_to_mfn_frame_list; + unsigned long max_pfn; /* max pfn that appears in table */ + unsigned long pfn_to_mfn_frame_list_list; + /* frame containing list of mfns + containing list of mfns + containing the p2m table. */ } arch_shared_info_t; #endif /* !__ASSEMBLY__ */ -- 2.30.2